package taskmanager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import taskinstance.*;

/**
 * @author ryan
 * Task manager class, also called task scheduler.
 * 
 */
public class TaskManager {
  private ScheduledThreadPoolExecutor stpeExecutor = new ScheduledThreadPoolExecutor(100);

  private ArrayList<Task> completeList = new ArrayList<Task>();
  private ArrayList<Task> runningList = new ArrayList<Task>();
  private ArrayList<Task> failedList = new ArrayList<Task>();

  private ReentrantLock[] directionLocks;
  private HashMap<String, Integer> ipToIndexMap = new HashMap<String, Integer>();

  public TaskManager(String[] ips) {
    directionLocks = new ReentrantLock[ips.length];
    for (String ip : ips) {
      directionLocks[ipToIndexMap.size()] = new ReentrantLock();
      ipToIndexMap.put(ip, ipToIndexMap.size());
    }
  }

  public void addTask(Task tsk) {
    runningList.add(tsk);
    tsk.setObserver(this);
    
    if (tsk instanceof InstantTask) {
      stpeExecutor.schedule(tsk, 0, TimeUnit.SECONDS);
    } else if (tsk instanceof TimingTask) {
      stpeExecutor.schedule(tsk, ((TimingTask) tsk).getDelayTime(), TimeUnit.MILLISECONDS);
    } else if (tsk instanceof PeriodTask) {
      stpeExecutor.scheduleAtFixedRate(tsk, 0, ((PeriodTask) (tsk)).getDuringTime(),
          TimeUnit.SECONDS);
    } else {

    }
  }

  public void queryTaskState() {
    synchronized (runningList) {
      System.out.println("###########################");

      System.out.println("Running Task\n");
      System.out.println("Pro\tDes\tFile");
      for (Task t : runningList) {
        if (!t.isPending()) {
          System.out.println(t.getProgress() + '\t' + t.toString());
        }
      }
      System.out.println("\n-------------------------");

      System.out.println("Pending Task\n");
      System.out.println("Des\tFile");
      for (Task t : runningList) {
        if (t.isPending()) {
          System.out.println(t);
        }
      }
      System.out.println("\n-------------------------");


      System.out.println("Complete Task\n");
      if (completeList.size() > 0) {
        System.out.println("Des\tFile");
      }
      for (Task t : completeList) {
        System.out.println(t);
      }
      System.out.println("\n-------------------------");


      System.out.println("Failed Task\n");
      if (failedList.size() > 0) {
        System.out.println("Des\tFile");
      }
      for (Task t : failedList) {
        System.out.println(t);
      }
      System.out.println("\n-------------------------");
      System.out.println("###########################\n\n");
    }
  }

  public void suspendTask(Task t) {
    t.suspend();
  }

  public void resumeTask(Task t) {
    t.resume();
  }

  public void lockTargetIp(String ip) {
    directionLocks[ipToIndexMap.get(ip)].lock();
  }

  public void releaseTargetIp(String ip) {
    directionLocks[ipToIndexMap.get(ip)].unlock();
  }

  public ArrayList<Task> getCompleteList() {
    return completeList;
  }

  public ArrayList<Task> getRunningList() {
    return runningList;
  }

  public ArrayList<Task> getFailedList() {
    return failedList;
  }
}
